/*
 *    Copyright (c) 2018-2025, lengleng All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * Neither the name of the pig4cloud.com developer nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 * Author: lengleng (wangiegie@gmail.com)
 */
package com.pig4cloud.pig.ads.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.pig4cloud.pig.ads.gdt.service.GdtAccesstokenService;
import com.pig4cloud.pig.ads.pig.mapper.AdMaterialCoverMapper;
import com.pig4cloud.pig.ads.service.AdMaterialCoverPlatformService;
import com.pig4cloud.pig.ads.service.AdMaterialCoverService;
import com.pig4cloud.pig.ads.service.TtAccesstokenService;
import com.pig4cloud.pig.ads.utils.OEHttpUtils;
import com.pig4cloud.pig.api.entity.AdMaterialCover;
import com.pig4cloud.pig.api.entity.AdMaterialCoverPlatform;
import com.pig4cloud.pig.api.entity.AdMaterialPlatform;
import com.pig4cloud.pig.api.entity.ResponseBean;
import com.pig4cloud.pig.common.core.constant.enums.PlatformTypeEnum;
import com.pig4cloud.pig.common.core.util.R;
import com.pig4cloud.pig.common.security.util.SecurityUtils;
import com.pig4cloud.pig.api.util.MapUtils;
import com.pig4cloud.pig.api.vo.AdMaterialCoverVo;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.*;
import java.net.URI;
import java.util.*;

/**
 * 素材视频封面图
 *
 * @author pigx code generator
 * @date 2021-06-23 14:32:25
 */
@Log4j2
@Service
@RequiredArgsConstructor
public class AdMaterialCoverServiceImpl extends ServiceImpl<AdMaterialCoverMapper, AdMaterialCover> implements AdMaterialCoverService {

	private final AdMaterialCoverPlatformService adMaterialCoverPlatformService;

	private final TtAccesstokenService ttAccesstokenService;

	private final GdtAccesstokenService gdtAccesstokenService;

	/**
	 * 广点通上传视频接口地址前缀
	 */
	@Value(value = "${gdt_url}")
	private String gdtUrl;
	/**
	 * 添加图片文件
	 */
	@Value(value = "${gdt_images_add_url}")
	private String gdtImagesAddUrl;

	/**
	 * 分页
	 * @param req
	 * @return
	 */
	@Override
	public R getPage(AdMaterialCoverVo req){
		QueryWrapper<AdMaterialCover> wrapper = new QueryWrapper<>();
		wrapper.eq("material_id",req.getMaterialId());
		wrapper.eq("status",0);
		wrapper.orderByAsc("id");
		IPage<AdMaterialCover> iPage = this.page(req,wrapper);
		return R.ok(iPage);
	}

	/**
	 * 封面图片推送
	 * @param req
	 * @return
	 */
	@Override
	public R pushCover(AdMaterialCoverVo req) throws IOException {
		List<AdMaterialCoverPlatform> resultList = Lists.newArrayList();
		String[] ids = req.getIds().split(",");
		for (String coverId : ids) {
			AdMaterialCover adMaterialCover = this.getById(coverId);
			if (Objects.isNull(adMaterialCover)){
				return R.failed("未获取到封面图片信息");
			}
			String[] advertiserIds = req.getAdvertiserIds().split(",");
			for (String advertiserId : advertiserIds) {
				// 判断是否已经同步
				AdMaterialCoverPlatform materialCoverPlatform = adMaterialCoverPlatformService.getOne(Wrappers.<AdMaterialCoverPlatform>query().lambda()
						.eq(AdMaterialCoverPlatform::getCoverId,adMaterialCover.getId())
						.eq(AdMaterialCoverPlatform::getAdvertiserId,advertiserId).last("LIMIT 1"));
				if (Objects.isNull(materialCoverPlatform)){
					R result = new R();
					if (PlatformTypeEnum.TT.getValue().equals(req.getPlatformId())){
						// 头条 图片
						result = pushPictureToutiao(advertiserId,adMaterialCover);
					}else if (PlatformTypeEnum.GDT.getValue().equals(req.getPlatformId())){
						// 广点通 图片
						result = pushPictureGdt(advertiserId,adMaterialCover);
					}
					if (0 == result.getCode()){
						AdMaterialCoverPlatform adMaterialCoverPlatform = (AdMaterialCoverPlatform) result.getData();
						resultList.add(adMaterialCoverPlatform);
					}else{
						return R.failed(result.getMsg());
					}
				}else{
					resultList.add(materialCoverPlatform);
				}
			}
		}
		return R.ok(resultList);
	}
	/**
	 * 图片上传头条
	 * @param advertiserId 广告账户
	 * @param adMaterialCover 视频素材信息对象
	 * @return
	 */
	public R pushPictureToutiao(String advertiserId, AdMaterialCover adMaterialCover){
		//定义头条接口url
		String url = "https://ad.oceanengine.com/open_api/2/file/image/ad/";

		Map<String, Object> data = new HashMap<String, Object>();
		data.put("advertiser_id", advertiserId);
		data.put("upload_type","UPLOAD_BY_URL");
		data.put("image_url",adMaterialCover.getFileUrl());
		data.put("filename",adMaterialCover.getFileName());
		//公共方法获取accessToken
		String accessToken = ttAccesstokenService.fetchAccesstoken(advertiserId);
		//调第三方平台（头条）接口
		String resultStr = OEHttpUtils.doPost(url, data, accessToken);
		ResponseBean resBean = JSON.parseObject(resultStr, ResponseBean.class);
		//调用成功
		if(resBean != null && "0".equals(resBean.getCode())){
			Map<String,Object> resData = resBean.getData();
			AdMaterialCoverPlatform adp = new AdMaterialCoverPlatform();
			// 1 头条
			adp.setPlatformId(Integer.valueOf(PlatformTypeEnum.TT.getValue()));
			adp.setCoverId(adMaterialCover.getId().intValue());
			// 广告账户
			adp.setAdvertiserId(advertiserId);
			adp.setPlatformFileId(String.valueOf(resData.get("id")));
			adp.setPlatformMaterialId(String.valueOf(resData.get("material_id")));
			adp.setMd5(adMaterialCover.getMd5());
			adp.setCreateUser(String.valueOf(SecurityUtils.getUser().getId()));
			adp.setCreateTime(new Date());

			adMaterialCoverPlatformService.save(adp);
			return R.ok(adp);
		}else{
			return R.failed("图片同步头条失败：" + resBean.getMessage());
		}
	}
	/**
	 * 图片上传广点通
	 * @param advertiserId 广告账户
	 * @param adMaterialCover 视频素材信息对象
	 * @return
	 */
	public R pushPictureGdt(String advertiserId,AdMaterialCover adMaterialCover) throws IOException {
		//公共方法获取accessToken
		Map<String, String> map = gdtAccesstokenService.fetchAccesstoken(advertiserId);
		//定义广点通接口url
		String url = gdtUrl + gdtImagesAddUrl + "?" + MapUtils.queryString(map);
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("account_id", advertiserId);
		params.put("upload_type", "UPLOAD_TYPE_FILE");
		String md5 = DigestUtils.md5Hex(new FileInputStream(adMaterialCover.getRealPath()));
		params.put("signature", md5);
		params.put("realPath", adMaterialCover.getRealPath());
		//调第三方平台（头条）接口
		JSONObject resultStr = synPicGdtPost(url, params);
		ResponseBean resBean = JSON.parseObject(resultStr.toJSONString(), ResponseBean.class);
		//调用成功
		if (resBean != null && resBean.getCode() != null && "0".equals(resBean.getCode())) {
			Map<String, Object> data = resBean.getData();
			AdMaterialCoverPlatform adp = new AdMaterialCoverPlatform();
			// 2 广点通
			adp.setPlatformId(Integer.valueOf(PlatformTypeEnum.GDT.getValue()));
			adp.setCoverId(adMaterialCover.getId().intValue());
			// 广告账户
			adp.setAdvertiserId(advertiserId);
			adp.setPlatformFileId(String.valueOf(data.get("image_id")));
			adp.setPlatformMaterialId(String.valueOf(data.get("image_id")));
			adp.setMd5(adMaterialCover.getMd5());
			adp.setCreateUser(String.valueOf(SecurityUtils.getUser().getId()));
			adp.setCreateTime(new Date());

			adMaterialCoverPlatformService.save(adp);
			return R.ok(adp);
		}else{
			return R.failed("图片同步广点通失败：" + resBean.getMessage());
		}
	}
	//广点通：推送图片 请求
	public static JSONObject synPicGdtPost(String url, Map<String, Object> data) {
		// 构造请求
		HttpPost httpPost = new HttpPost(url);
		// 文件参数
		FileBody file = new FileBody(new File(String.valueOf(data.get("realPath"))));
		MultipartEntityBuilder entityBuilder = MultipartEntityBuilder.create()
				.addPart("file", file);
		// 其他参数
		entityBuilder.addTextBody("account_id", String.valueOf(data.get("account_id")));
		entityBuilder.addTextBody("upload_type", String.valueOf(data.get("upload_type")));
		entityBuilder.addTextBody("signature", String.valueOf(data.get("signature")), ContentType.APPLICATION_JSON);
		HttpEntity entity = entityBuilder.build();
		CloseableHttpResponse response = null;
		CloseableHttpClient client = null;
		try {
			client = HttpClientBuilder.create().build();
			httpPost.setURI(URI.create(url));

			httpPost.setEntity(entity);

			response = client.execute(httpPost);
			if (response != null && response.getStatusLine().getStatusCode() == 200) {
				BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
				StringBuffer result = new StringBuffer();
				String line = "";
				while ((line = bufferedReader.readLine()) != null) {
					result.append(line);
				}
				bufferedReader.close();
				return JSONObject.parseObject(result.toString());
			}
		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if (response != null) {
					response.close();
				}
				client.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return new JSONObject();
	}
}
